package com.zxd.interview.eightthread.executoreervicetest;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 *  ExecutorService 使用实战
 * @author Xander
 * @version v1.0.0
 * @Package : com.zxd.interview.eightthread.executoreervicetest
 * @Description : ExecutorService 使用实战
 * @Create on : 2023/3/16 11:36
 **/
public class ExecutorServiceTest
{

    public static void main(String[] args) throws ExecutionException, InterruptedException {
//        newExecutorService();
        assignTaskToExecutor();
    }

    /**
     * 不推荐使用除开
     */
    @Deprecated
    private static ExecutorService newExecutorService() {
        ExecutorService executorService =
                new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
                        new LinkedBlockingQueue<Runnable>());
        return executorService;
    }

    public static void assignTaskToExecutor() throws ExecutionException, InterruptedException {

        Runnable runnableTask = () -> {
            try {
                System.out.println(Thread.currentThread().getName()+" runnableTask");
                TimeUnit.MILLISECONDS.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };

        Callable<String> callableTask = () -> {
            System.out.println(Thread.currentThread().getName()+" callableTask");
            TimeUnit.MILLISECONDS.sleep(300);
            return "Task's execution "+Thread.currentThread().getName();
        };



        List<Callable<String>> callableTasks = new ArrayList<>();
        callableTasks.add(callableTask);
        callableTasks.add(callableTask);
        callableTasks.add(callableTask);
        ExecutorService executorService = newExecutorService();
        executorService.execute(runnableTask);
        Future<?> submit = executorService.submit(runnableTask);
        // runable返回结果为null
        Object o = submit.get();
        System.out.println(o);
        /**
         pool-1-thread-1 runnableTask
         pool-1-thread-1 runnableTask
         Runnable的返回结果为null
         null
         */

        for (Callable<String> task : callableTasks) {

            Future<?> callResult = executorService.submit(task);
            Object callRes = callResult.get();
            System.err.println(callRes);
        }/**
         pool-1-thread-1 callableTask
         Task's execution
         pool-1-thread-1 callableTask
         Task's execution
         pool-1-thread-1 callableTask
         Task's execution
         */
        System.out.println("\n");
        String result = executorService.invokeAny(callableTasks);
        System.out.println("invokeAny => "+result);
        /**
         pool-1-thread-1 callableTask
         pool-1-thread-1 callableTask
         Task's executionpool-1-thread-1
         */


        System.out.println("\n");
        System.out.println("\n");
        List<Future<String>> futures = executorService.invokeAll(callableTasks);
        for (Future<String> future : futures) {
            System.out.println("是否完成："+ future.isDone());
            System.out.println("收到回调：" + future.get());
        }/**
         callAble 的接口实现回调结果：
         pool-1-thread-1 callableTask
         pool-1-thread-1 callableTask
         pool-1-thread-1 callableTask
         收到回调Task's execution pool-1-thread-1
         收到回调Task's execution pool-1-thread-1
         收到回调Task's execution pool-1-thread-1
         */

        /**
         * 判断是否完成
         * pool-1-thread-1 callableTask
         * pool-1-thread-1 callableTask
         * pool-1-thread-1 callableTask
         * 是否完成：true
         * 收到回调：Task's execution pool-1-thread-1
         * 是否完成：true
         * 收到回调：Task's execution pool-1-thread-1
         * 是否完成：true
         * 收到回调：Task's execution pool-1-thread-1
         * */

        // 关闭线程池
//        executorService.shutdown();
//        Runnable runnableTask2 = () -> {
//            try {
//                System.out.println(Thread.currentThread().getName()+" runnableTask");
//                TimeUnit.MILLISECONDS.sleep(30000);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//        };
//        executorService.execute(runnableTask2);
        //具备返回值
//        List<Runnable> runnables = executorService.shutdownNow();
        /**
         * 如果是一个很长的睡眠任务，则会中断
         * java.lang.InterruptedException: sleep interrupted
         * 	at java.base/java.lang.Thread.sleep(Native Method)
         * 	at java.base/java.lang.Thread.sleep(Thread.java:339)
         * 	at java.base/java.util.concurrent.TimeUnit.sleep(TimeUnit.java:446)
         * 	at com.zxd.interview.eightthread.executoreervicetest.ExecutorServiceTest.lambda$assignTaskToExecutor$2(ExecutorServiceTest.java:111)
         * 	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
         * 	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
         * 	at java.base/java.lang.Thread.run(Thread.java:834)
         * */
//        for (Runnable runnable : runnables) {
//            Thread thread = new Thread(runnable);
//            thread.setName("处理未结束内容");
//            thread.run();
//            System.out.println("补偿，继续运行 " );
//        }


//        executorService.shutdown();


        System.out.println("\n");
        System.out.println("\n");
        // 延长等待时间的回调任务
        ExecutorService executorService2 = newExecutorService();
        Callable<String> callableTask3 = () -> {
            System.out.println(Thread.currentThread().getName()+" callableTask");
//            TimeUnit.MILLISECONDS.sleep(300);
            // 延长等待时间
            TimeUnit.MILLISECONDS.sleep(30000);
            return "Task's execution "+Thread.currentThread().getName();
        };

        Future<String> submit1 = executorService2.submit(callableTask3);
        submit1.cancel(true);
        // 如果一个任务 cancel 之后进行get，会抛出异常
        /*
        Exception in thread "main" java.util.concurrent.CancellationException
        at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:121)
        at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191)
        at com.zxd.interview.eightthread.executoreervicetest.ExecutorServiceTest.assignTaskToExecutor(ExecutorServiceTest.java:171)
        at com.zxd.interview.eightthread.executoreervicetest.ExecutorServiceTest.main(ExecutorServiceTest.java:20)
        * */
//        System.out.println("取消执行任务"+submit1.get());
        System.out.println("是否取消执行任务："+ submit1.isCancelled());
        /**
         * 是否取消执行任务：true
         * */


        // 最佳实践 shutdownNow 和 awaitTermination 方法结合使用
        try {
            if (!executorService.awaitTermination(800, TimeUnit.MILLISECONDS)) {
                executorService.shutdownNow();
            }
        } catch (InterruptedException e) {
            executorService.shutdownNow();
        }


        // 下面的代码在执行callableTask之前延迟了一秒。
        System.out.println("\n");
        System.out.println("\n");
        Callable<String> scheduleCall = () -> {
            System.out.println(Thread.currentThread().getName()+" callableTask");
            TimeUnit.MILLISECONDS.sleep(300);
            return "Task's execution "+Thread.currentThread().getName();
        };
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors());
        Future<String> resultFuture =
                scheduledExecutorService.schedule(scheduleCall, 1, TimeUnit.SECONDS);
        System.out.println("resultFuture => "+ resultFuture.get());
        /**
         *
         pool-3-thread-1 callableTask
         resultFuture => Task's execution pool-3-thread-1
         * */

        System.out.println("\n");
        //下面的代码块将在100毫秒的初始延迟后运行一个任务。此后，它将每隔**450毫秒**运行一次相同的任务
        scheduledExecutorService.scheduleAtFixedRate(runnableTask, 100, 450, TimeUnit.MILLISECONDS);


        // 下面的代码将保证在当前执行结束和另一个执行开始之间有150毫秒的停顿
        scheduledExecutorService.scheduleWithFixedDelay(runnableTask, 100, 150, TimeUnit.MILLISECONDS);

        /*

        注意任务的周期执行将在ExecutorService**终止**时或在任务执行期间**抛出异常**时结束。
        pool-3-thread-1 runnableTask
pool-3-thread-2 runnableTask
pool-3-thread-3 runnableTask
pool-3-thread-2 runnableTask
java.lang.InterruptedException: sleep interrupted
	at java.base/java.lang.Thread.sleep(Native Method)
	at java.base/java.lang.Thread.sleep(Thread.java:339)
	at java.base/java.util.concurrent.TimeUnit.sleep(TimeUnit.java:446)
	at com.zxd.interview.eightthread.executoreervicetest.ExecutorServiceTest.lambda$assignTaskToExecutor$0(ExecutorServiceTest.java:39)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
	at java.base/java.util.concurrent.FutureTask.runAndReset$$$capture(FutureTask.java:305)
	at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java)
	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:834)
java.lang.InterruptedException: sleep interrupted
	at java.base/java.lang.Thread.sleep(Native Method)
	at java.base/java.lang.Thread.sleep(Thread.java:339)
	at java.base/java.util.concurrent.TimeUnit.sleep(TimeUnit.java:446)
	at com.zxd.interview.eightthread.executoreervicetest.ExecutorServiceTest.lambda$assignTaskToExecutor$0(ExecutorServiceTest.java:39)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
	at java.base/java.util.concurrent.FutureTask.runAndReset$$$capture(FutureTask.java:305)
	at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java)
	at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:834)
        * */

        try {
            if (!scheduledExecutorService.awaitTermination(4000, TimeUnit.MILLISECONDS)) {
                scheduledExecutorService.shutdownNow();
            }
        } catch (InterruptedException e) {
            scheduledExecutorService.shutdownNow();
        }/**
         pool-3-thread-1 runnableTask
         pool-3-thread-2 runnableTask

         java.lang.InterruptedException: sleep interrupted
         at java.base/java.lang.Thread.sleep(Native Method)
         at java.base/java.lang.Thread.sleep(Thread.java:339)
         at java.base/java.util.concurrent.TimeUnit.sleep(TimeUnit.java:446)
         at com.zxd.interview.eightthread.executoreervicetest.ExecutorServiceTest.lambda$assignTaskToExecutor$0(ExecutorServiceTest.java:39)
         */



        executorService2.shutdown();

    }
}
